import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: DragSortGridPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class DragSortGridPage extends StatefulWidget {
  const DragSortGridPage({super.key});

  @override
  State<DragSortGridPage> createState() => _DragSortGridPageState();
}

class _DragSortGridPageState extends State<DragSortGridPage>
    with TickerProviderStateMixin {
  List<String> items = List.generate(12, (index) => 'Item ${index + 1}');

  int? draggingIndex;
  Offset? dragStart;
  Offset? dragPosition;

  @override
  Widget build(BuildContext context) {
    double itemSize = (MediaQuery.of(context).size.width - 80) / 3;

    return Scaffold(
      appBar: AppBar(
        title: const Text("原生可拖动排序 GridView"),
        centerTitle: true,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: LayoutBuilder(
          builder: (context, constraints) {
            return Stack(
              children: [
                GridView.builder(
                  physics: const NeverScrollableScrollPhysics(),
                  itemCount: items.length,
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    crossAxisSpacing: 16,
                    mainAxisSpacing: 16,
                  ),
                  itemBuilder: (context, index) {
                    bool isDragging = draggingIndex == index;
                    return GestureDetector(
                      onLongPressStart: (details) {
                        setState(() {
                          draggingIndex = index;
                          dragStart = details.globalPosition;
                          dragPosition = dragStart;
                        });
                      },
                      onLongPressMoveUpdate: (details) {
                        setState(() {
                          dragPosition = details.globalPosition;
                        });
                        _checkForReorder(index, details.globalPosition, itemSize);
                      },
                      onLongPressEnd: (_) {
                        setState(() {
                          draggingIndex = null;
                          dragStart = null;
                          dragPosition = null;
                        });
                      },
                      child: AnimatedScale(
                        scale: isDragging ? 1.1 : 1.0,
                        duration: const Duration(milliseconds: 200),
                        child: Opacity(
                          opacity: isDragging ? 0.0 : 1.0,
                          child: _buildItem(items[index]),
                        ),
                      ),
                    );
                  },
                ),
                // 拖动中的 widget
                if (draggingIndex != null && dragPosition != null)
                  Positioned(
                    left: dragPosition!.dx - itemSize / 2,
                    top: dragPosition!.dy - itemSize / 2 - 100,
                    child: IgnorePointer(
                      child: AnimatedScale(
                        scale: 1.2,
                        duration: const Duration(milliseconds: 200),
                        child: _buildItem(items[draggingIndex!]),
                      ),
                    ),
                  ),
              ],
            );
          },
        ),
      ),
    );
  }

  /// 构建单个网格 item
  Widget _buildItem(String title) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.blueAccent,
        borderRadius: BorderRadius.circular(12),
        boxShadow: const [
          BoxShadow(color: Colors.black26, blurRadius: 6, offset: Offset(2, 2)),
        ],
      ),
      alignment: Alignment.center,
      child: Text(
        title,
        style: const TextStyle(
            color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16),
      ),
    );
  }

  /// 检查是否需要交换位置
  void _checkForReorder(int currentIndex, Offset globalPosition, double itemSize) {
    int targetIndex = _calculateTargetIndex(globalPosition, itemSize);
    if (targetIndex != currentIndex &&
        targetIndex >= 0 &&
        targetIndex < items.length) {
      setState(() {
        final item = items.removeAt(currentIndex);
        items.insert(targetIndex, item);
        draggingIndex = targetIndex;
      });
    }
  }

  /// 根据手指位置计算目标索引
  int _calculateTargetIndex(Offset globalPosition, double itemSize) {
    RenderBox box = context.findRenderObject() as RenderBox;
    Offset local = box.globalToLocal(globalPosition);
    int col = (local.dx / (itemSize + 16)).floor();
    int row = (local.dy / (itemSize + 16)).floor();
    int index = row * 3 + col;
    return index;
  }
}
